package cn.funnymap.lgis.tools.vector.parser;

import cn.funnymap.lgis.tools.exception.ShpParserRuntimeException;
import cn.funnymap.lgis.tools.file.FileUtil;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.WKTWriter2;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * Shapefile属性解析器
 *
 * @author jiaoxn
 */
public class ShpAttributeValueParser extends ShpParser<List<ShpAttributeValue>> {
    public ShpAttributeValueParser(ShpParseParameter parseParameter) {
        super(parseParameter);
    }

    @Override
    List<ShpAttributeValue> parseShapefile() {
        List<ShpAttributeValue> shpAttributeValueList = new ArrayList<>();

        for (Path shpFilePath : this.processorParameter.getShpFilePathList()) {
            List<Map<String, Object>> shpFileValues = this.getShpAttribute(shpFilePath);
            shpAttributeValueList.add(new ShpAttributeValue(shpFileValues));
        }

        return shpAttributeValueList;
    }
    private List<Map<String, Object>> getShpAttribute(Path shpFilePath) {
        List<Map<String, Object>> attrList = new ArrayList<>();

        try {
            // 通过.dbf文件读取文件编码，并设置编码【防止中文乱码】
            String dbfFilePath = shpFilePath.toAbsolutePath().toString().replace(".shp", ".dbf");
            Path dbfPath = Paths.get(dbfFilePath);
            String encoding = FileUtil.detectEncoding(dbfPath);

            Map<String, Object> params = new HashMap<>();
            params.put("url", shpFilePath.toFile().toURI().toURL());
            params.put(ShapefileDataStoreFactory.DBFCHARSET.key, encoding);

            // 使用DataStoreFinder来创建DataStore
            DataStore dataStore = DataStoreFinder.getDataStore(params);

            // 获取FeatureSource，它表示地理数据的一个集合
            String typeName = dataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = dataStore.getFeatureSource(typeName);

            // 如果没有过滤器，则获取所有要素
            FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = featureSource.getFeatures();

            // 使用迭代器遍历所有要素
            try (SimpleFeatureIterator iterator = ((SimpleFeatureCollection) featureCollection).features()) {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();
                    SimpleFeatureType featureType = feature.getFeatureType();

                    Map<String, Object> featureAttr = new LinkedHashMap<>();

                    // 遍历每个属性
                    for (int i = 0; i < featureType.getAttributeCount(); i++) {
                        String attributeName = featureType.getDescriptor(i).getLocalName();
                        Object attribute = feature.getAttribute(i);

                        if ("the_geom".equals(attributeName)) {
                            attribute = geometry2wkt((Geometry) attribute);
                        }

                        featureAttr.put(attributeName, attribute);
                    }

                    attrList.add(featureAttr);
                }
            }

            dataStore.dispose();
        } catch (IOException e) {
            throw new ShpParserRuntimeException(e.getMessage());
        }

        return attrList;
    }

    private String geometry2wkt(Geometry geometry) {
        WKTWriter2 wktWriter = new WKTWriter2();
        return wktWriter.write(geometry);
    }
}
